package network;

import guimessage.FileUpload;
import guimessage.NotifNetwork;

import itdb1.commun.*;


import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

import controller.GUIController;

public class UploaderTCPClient extends TCPClient {

	protected FileUpload proposal;
	private GUIController guicontroller;
	private ObjectOutputStream outs;
	private ObjectInputStream ins;
	
	public UploaderTCPClient(FileUpload proposal, int port) throws IOException {
		super( new Socket(proposal.getContact().getIpAddr(), port));
		guicontroller = GUIController.getInstance();
		this.proposal = proposal;
	}

	@Override
	public void run() {
		guicontroller.writeDebugScreen("UploaderTCPClient > launched\n");
		
		sendFileDescription(proposal.getFilename(), proposal.getSize());
		guicontroller.writeDebugScreen("UploaderTCPClient > file proposal sent\n");
		
		FileAnswer answer = receiveFileAnswer();
		if( answer.isAccepted() )
		{
			guicontroller.writeDebugScreen("UploaderTCPClient > file proposal accepted\n");
			if( sendFile( proposal.getPath(), proposal.getSize() ) )
			{
				guicontroller.writeDebugScreen("UploaderTCPClient > file has been sent\n");
				guicontroller.messages.add(new NotifNetwork(sock.getInetAddress(), "Upload succeeded"));
			}
			else
			{
				guicontroller.messages.add(new NotifNetwork(sock.getInetAddress(), "Upload failed"));
				guicontroller.writeDebugScreen("UploaderTCPClient > file has not been sent !\n");
			}
		}
		else
		{
			guicontroller.writeDebugScreen("UploaderTCPClient > proposal refused !");
			guicontroller.messages.add(new NotifNetwork(sock.getInetAddress(), "Your proposition has been refused"));
		}
		
		closeConnection();
	}
	
	private boolean sendFileDescription(String name, int size)
	{
		try{
			outs = new ObjectOutputStream(sock.getOutputStream());
		
			outs.writeObject( new FileDescription(name, size) );
			outs.flush();
			
			return true;
		}
		catch(IOException ioException)
		{
			ioException.printStackTrace();
			return false;
		}
	}
	
	private FileAnswer receiveFileAnswer()
	{
		FileAnswer answer = null;
		
		try
		{
			ins = new ObjectInputStream(sock.getInputStream());
			
			answer = (FileAnswer) ins.readObject();
		}
		catch(IOException ioException)
		{
			ioException.printStackTrace();
		}
		catch (ClassNotFoundException e)
		{
			e.printStackTrace();
		}
		
		return answer;
	}
	
	// à améliorer
	private boolean sendFile(String path, int fileLength)
	{
		FileInputStream uploadedFileStream = null;
		BufferedOutputStream  bufferOutSocket = null;
		
		try
		{
			uploadedFileStream = new FileInputStream(new File(path));
			bufferOutSocket = new BufferedOutputStream(sock.getOutputStream());
			
			
			// Il va falloir penser ici à faire une liaison avec le controleur de gui pour informer l'utilisateur de la progression
			int sentBytes = 0;
			while(sentBytes < fileLength)
			{
				byte[] buffer = new byte[1024];
				int b;
				
				b = uploadedFileStream.read(buffer);
				if(b > 0)
				{
					sentBytes += b;
					bufferOutSocket.write(buffer);
				}	
			}
		}
		catch(IOException ioException)
		{
			ioException.printStackTrace();
			return false;
		}
		finally
		{
			try
			{
				uploadedFileStream.close();
				bufferOutSocket.close();
			}
			catch(IOException ioException)
			{
				ioException.printStackTrace();
			}
		}
		
		return true;
	}
	
	private void closeConnection()
	{
		if(sock != null)
		{
			try{
				sock.close();
			}
			catch(IOException ioException)
			{
				ioException.printStackTrace();
			}
		}
	}
}
